<?php
/*
 * MiniMe - a minimalistic OStatus complient microblogging tool
 * Copyright (C) 2010, Tuomas Koski - koski.tuomas@gmail.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

$basedir = dirname(__FILE__);

// These files will be always needed for the Magic Stuff.
// Maybe the right place is not here.
require_once $basedir . '/../../extlib/Crypt/RSA.php';
require_once $basedir . '/../../extlib/Crypt/Random.php';
require_once $basedir . '/../../extlib/Crypt/Hash.php';
require_once $basedir . '/../../extlib/Math/BigInteger.php';

/**
 * @author     Tuomas Koski <koski.tuomas@gmail.com>
 * @copyright  Tuomas Koski
 * @license    http://www.gnu.org/licenses/lgpl.txt
 */
class Controller_Salmon extends Controller_Abstract implements Controller_Interface {
    
    public function __construct($getParams, $postParams, $phpInput, $conf) {
        
        parent::__construct($getParams, $postParams, $phpInput, $conf);
        
    }
    
    public function execute () {
        
        file_put_contents ("/tmp/minime-salmon.input", print_r(apache_request_headers(), true) . "\nPOST:\n" . print_r($this->postParams, true) . "\nGET:\n" . print_r($this->getParams, true) . "\nRAW:\n" . $this->phpInput);
        
        $userLoader = new Minime_User_Loader($this->conf);
        $user = $userLoader->getUser($this->getParams['username']);
        
        if(!$user) {
            $this->headers[404] = "HTTP/1.0 404 Not Found";
            $this->output = "Salmon you requested was not found.";
            file_put_contents ("/tmp/minime-salmon.output", "Salmon you requested was not found.");
            return; 
        }
        
        $magicEnv = Magic_Envelope::buildFromRawXML($this->phpInput);
        file_put_contents ("/tmp/minime-salmon-decoded.input", $magicEnv->getDecodedData());
        
        $atom = Atom_Entry::buildFromRawXML($magicEnv->getDecodedData());

        // Let's try to find the publicKey
        $uri = $atom->getAuthor()->getUri()->getUri();
        
        $discoverer = new Discovery_Uri($uri);
        if(!$discoverer->discover()) {
            $this->headers[400] = "HTTP/1.0 400 Bad Request";
            $this->output = "Cannot verify signature. Cannot discover the sender's uri. (" . $uri . ")";
            file_put_contents ("/tmp/minime-salmon.output-error", "Cannot verify signature. Cannot discover the sender's uri. (" . $uri . ")");
            return;
        }
        
        $publicKey = $discoverer->getMagicPublicKey();
        $publicKey = str_replace("data:application/magic-public-key,", "", $publicKey);
        
        $verifyier = new Magic_Signature_Verify($publicKey);
        if(!$verifyier->magicEnvelopeHasValidSignature($magicEnv)) {
            $this->headers[400] = "HTTP/1.0 400 Bad Request";
            $this->output = "Cannot verify signature. There seems to be something wrong in that.";
            file_put_contents ("/tmp/minime-salmon.output", "Cannot verify signature. There seems to be something wrong in that.");
            return;
        }
        
        if($atom->getActivitystreamVerb() === null || 
           $atom->getActivitystreamVerb()->getVerb()== Activitystream_Verb::VERB_POST) {
            
            // OK, let's see if we are subscribed to a user:
            $subsloader = new Minime_User_Subscriptions_Loader($this->conf);
            $usersSubscriptions = $subsloader->getSubscriptions($this->getParams['username']);
//            if($usersSubscriptions->getSubscriptionByUri($uri) !== null) {
//                // We are subscribed to this user so we propably have the same reply from the atom feed
//                // Let's scip this one.
//                file_put_contents ("/tmp/minime-salmon.output", "Atom from someone we are subscribed to.");
//                // This is crap here! Remove this if!
//                //TODO, finish this!
//                // USE Atom_Feed::addEntry 
//                return;
//            }
            
            // By the way, this next piece of code keeps appearing and appearing in many places.
            $atomLoader = new Minime_Atom_Loader(MiniMe::$conf);
            $feed = $atomLoader->getFeed($this->getParams['username']);
            
            $feed->addEntry($atom);
            
            $feed->updateUpdated();
            
            $atomStorer = new Minime_Atom_Storer(MiniMe::$conf);
            $atomStorer->storeAtom($this->getParams['username'], $feed);
            
            file_put_contents ("/tmp/minime-salmon.output", "No verb or post verb. Added to atom.");
        } else if($atom->getActivitystreamVerb()->getVerb() == Activitystream_Verb::VERB_FOLLOW) {
        
            $subsloader = new Minime_User_Subscribers_Loader($this->conf);
            $usersSubscribers = $subsloader->getSubscribers($this->getParams['username']);

            $array['uri'] = $uri;
            $array['name'] = $discoverer->getName();
            $array['atomfeed'] = $discoverer->getAtomFeedUri();
            $array['alternate'] = $discoverer->getWebfingerProfilePageUri();
            $array['logo'] = $discoverer->getLogo();
                
            $usersSubscribers->addSubscriber(Minime_User_Subscriber::buildFromArray($array));
    
            $substorer = new Minime_User_Subscribers_Storer($this->conf);
            $substorer->storeSubscribers($this->getParams['username'], $usersSubscribers);
        
            $atomLoader = new Minime_Atom_Loader(MiniMe::$conf);
            $feed = $atomLoader->getFeed($this->getParams['username']);
            
            $feed->addChildElement($atom);
            
            $feed->updateUpdated();
            
            $atomStorer = new Minime_Atom_Storer(MiniMe::$conf);
            $atomStorer->storeAtom($this->getParams['username'], $feed);   
        } else if($atom->getActivitystreamVerb()->getVerb() == Activitystream_Verb::VERB_UNFOLLOW) {
            
            file_put_contents ("/tmp/minime-salmon.output", "Removing user '" . $uri . "'");
            
            $subsloader = new Minime_User_Subscribers_Loader($this->conf);
            $usersSubscribers = $subsloader->getSubscribers($this->getParams['username']);
            
            $usersSubscribers->removeSubscriber($uri);
            
            $substorer = new Minime_User_Subscribers_Storer($this->conf);
            $substorer->storeSubscribers($this->getParams['username'], $usersSubscribers);
            
            $atomLoader = new Minime_Atom_Loader(MiniMe::$conf);
            $feed = $atomLoader->getFeed($this->getParams['username']);
            
            $feed->addChildElement($atom);
            
            $feed->updateUpdated();
            
            $atomStorer = new Minime_Atom_Storer(MiniMe::$conf);
            $atomStorer->storeAtom($this->getParams['username'], $feed);
        } else {
            file_put_contents ("/tmp/minime-salmon.output-" . time(), "Nothing to do for verb '" . $atom->getActivitystreamVerb()->getVerb() . "' from '" . $uri . "'. Raw:\n" . $this->phpInput);
        }
    }
}